import * as path from 'path';
import * as webpack from 'webpack';
import type { Configuration } from 'webpack';
import devServer from './devServer';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import MiniCssExtractPlugin from 'mini-css-extract-plugin'; //将 CSS 提取到单独的文件中
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; //使用 cssnano 优化和压缩 CSS
import { WebpackManifestPlugin } from 'webpack-manifest-plugin';
import TerserPlugin from 'terser-webpack-plugin'; //压缩js
import CopyWebpackPlugin from 'copy-webpack-plugin';
import { CleanWebpackPlugin } from 'clean-webpack-plugin';
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;
const publicPathOrUrl = '/'; //要以/结尾
const publicUrl = publicPathOrUrl.slice(0, -1); //不以/结尾 使用时 publicUrl+'/img/logo.png'
// 如果使用 vscode Live Server右键启动index.html启动 publicPathOrUrl改为 /dist/
// Live Server 起始页为index.html 使用BrowserRouter会导致刷新页面出错，不刷新可预览，或者使用HashRouter
// 建议 使用 $ npm install -g serve  $ serve -s dist 的方式预览
function configFactory(env: any, argv: any): Configuration {
    // // console.log('运行参数:', env, argv);
    const isEnvDevelopment = env.development === true;
    const isEnvProduction = env.production === true;
    if (isEnvDevelopment) {
        process.env.BABEL_ENV = 'development';
        process.env.NODE_ENV = 'development';
    }
    if (isEnvProduction) {
        process.env.BABEL_ENV = 'production';
        process.env.NODE_ENV = 'production';
    }
    const stringified = {
        'process.env': {
            NODE_ENV: JSON.stringify(process.env.NODE_ENV),
            BABEL_ENV: JSON.stringify(process.env.BABEL_ENV),
            PUBLIC_URL: JSON.stringify(publicUrl),
            PUBLIC_PATH: JSON.stringify(publicPathOrUrl),
        },
    };

    // // console.log(process.cwd());
    // // console.log('argv', process.argv.slice(2));
    // // console.log(webpackEnv);
    // // console.log(process.env.PORT);
    // // console.log(process.env.HOST);
    // // console.log(process.env.HTTPS);
    // // console.log(process.env.CI);
    // // console.log(process.stdout.isTTY);
    // // console.log(process.env.TSC_COMPILE_ON_ERROR);
    // // console.log(process.env.PUBLIC_URL);
    // // console.log(process.env.GENERATE_SOURCEMAP);
    // // console.log(process.env.WDS_SOCKET_HOST);
    // // console.log(process.env.WDS_SOCKET_PATH);
    // // console.log(process.env.WDS_SOCKET_PORT);
    return {
        target: isEnvProduction ? ['browserslist'] : 'web',
        stats: 'errors-warnings',
        mode: isEnvProduction ? 'production' : 'development',
        // bail: isEnvProduction,
        devtool: isEnvProduction ? false : isEnvDevelopment && 'cheap-module-source-map',
        entry: path.resolve(__dirname, '../src/index.tsx'),
        output: {
            path: path.resolve(__dirname, '../dist'),
            pathinfo: isEnvDevelopment,
            filename: isEnvProduction ? 'static/js/[name].[contenthash:8].js' : 'static/js/bundle.js',
            chunkFilename: isEnvProduction ? 'static/js/[name].[contenthash:8].chunk.js' : 'static/js/[name].chunk.js',
            assetModuleFilename: 'static/media/[name].[hash][ext]',
            publicPath: publicPathOrUrl,
        },
        // infrastructureLogging: {
        //     level: 'none', //加上会不显示进度
        // },
        devServer: isEnvDevelopment ? devServer : undefined,
        optimization: {
            minimize: isEnvProduction,
            minimizer: [
                new TerserPlugin({
                    terserOptions: {
                        compress: {
                            ecma: 5,
                            comparisons: false,
                            inline: 2,
                        },
                        mangle: {
                            safari10: true,
                        },
                        keep_classnames: false,
                        keep_fnames: false,
                        output: {
                            ecma: 5,
                            comments: false,
                            ascii_only: true,
                        },
                    },
                }),
                new CssMinimizerPlugin(),
            ],
        },
        resolve: {
            extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
            fallback: {
                fs: false,
            },
            alias: {
                '@': path.resolve(__dirname, '../src'),
            },
        },
        module: {
            strictExportPresence: true,
            rules: [
                {
                    oneOf: [
                        {
                            test: /\.(js|jsx)$/,
                            use: {
                                loader: 'babel-loader',
                                options: {
                                    plugins: [],
                                    presets: ['@babel/preset-env', ['@babel/preset-react', { runtime: 'automatic' }]],
                                    sourceType: 'unambiguous',
                                },
                            },
                        },
                        {
                            test: /\.(ts|tsx)$/,
                            use: {
                                loader: 'babel-loader',
                                options: {
                                    plugins: [],
                                    presets: [
                                        '@babel/preset-env',
                                        ['@babel/preset-react', { runtime: 'automatic' }],
                                        '@babel/preset-typescript',
                                    ],
                                    sourceType: 'unambiguous',
                                },
                            },
                        },
                        {
                            test: cssRegex,
                            exclude: cssModuleRegex,
                            use: [
                                isEnvDevelopment && require.resolve('style-loader'),
                                isEnvProduction && {
                                    loader: MiniCssExtractPlugin.loader,
                                    options: {},
                                },
                                {
                                    loader: 'css-loader',
                                    options: {
                                        importLoaders: 1,
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                        modules: {
                                            mode: 'icss',
                                        },
                                    },
                                },
                                {
                                    loader: 'postcss-loader',
                                    options: {
                                        postcssOptions: {
                                            plugins: [
                                                'tailwindcss',
                                                'postcss-flexbugs-fixes',
                                                [
                                                    'postcss-preset-env',
                                                    {
                                                        autoprefixer: {
                                                            flexbox: 'no-2009',
                                                        },
                                                        stage: 3,
                                                    },
                                                ],
                                                'postcss-normalize',
                                            ],
                                        },
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                    },
                                },
                            ].filter(Boolean),
                            sideEffects: true,
                        },
                        {
                            test: cssModuleRegex,
                            use: [
                                isEnvDevelopment && require.resolve('style-loader'),
                                isEnvProduction && {
                                    loader: MiniCssExtractPlugin.loader,
                                    options: {},
                                },
                                {
                                    loader: 'css-loader',
                                    options: {
                                        importLoaders: 1,
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                        modules: {
                                            mode: 'local',
                                            localIdentName: '[local]_[hash:base64:6]',
                                        },
                                    },
                                },
                                {
                                    loader: 'postcss-loader',
                                    options: {
                                        postcssOptions: {
                                            plugins: [
                                                'tailwindcss',
                                                'postcss-flexbugs-fixes',
                                                [
                                                    'postcss-preset-env',
                                                    {
                                                        autoprefixer: {
                                                            flexbox: 'no-2009',
                                                        },
                                                        stage: 3,
                                                    },
                                                ],
                                                'postcss-normalize',
                                            ],
                                        },
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                    },
                                },
                            ].filter(Boolean),
                        },
                        {
                            test: sassRegex,
                            exclude: sassModuleRegex,
                            use: [
                                isEnvDevelopment && require.resolve('style-loader'),
                                isEnvProduction && {
                                    loader: MiniCssExtractPlugin.loader,
                                    options: {},
                                },
                                {
                                    loader: 'css-loader',
                                    options: {
                                        importLoaders: 3,
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                        modules: {
                                            mode: 'icss',
                                        },
                                    },
                                },
                                {
                                    loader: 'postcss-loader',
                                    options: {
                                        postcssOptions: {
                                            plugins: [
                                                'tailwindcss',
                                                'postcss-flexbugs-fixes',
                                                [
                                                    'postcss-preset-env',
                                                    {
                                                        autoprefixer: {
                                                            flexbox: 'no-2009',
                                                        },
                                                        stage: 3,
                                                    },
                                                ],
                                                'postcss-normalize',
                                            ],
                                        },
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                    },
                                },
                                {
                                    loader: require.resolve('sass-loader'),
                                    options: {
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                    },
                                },
                            ].filter(Boolean),
                            sideEffects: true,
                        },
                        {
                            test: sassModuleRegex,
                            use: [
                                isEnvDevelopment && require.resolve('style-loader'),
                                isEnvProduction && {
                                    loader: MiniCssExtractPlugin.loader,
                                    options: {},
                                },
                                {
                                    loader: 'css-loader',
                                    options: {
                                        importLoaders: 3,
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                        modules: {
                                            mode: 'local',
                                            localIdentName: '[local]_[hash:base64:6]',
                                        },
                                    },
                                },
                                {
                                    loader: 'postcss-loader',
                                    options: {
                                        postcssOptions: {
                                            plugins: [
                                                'tailwindcss',
                                                'postcss-flexbugs-fixes',
                                                [
                                                    'postcss-preset-env',
                                                    {
                                                        autoprefixer: {
                                                            flexbox: 'no-2009',
                                                        },
                                                        stage: 3,
                                                    },
                                                ],
                                                'postcss-normalize',
                                            ],
                                        },
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                    },
                                },
                                {
                                    loader: require.resolve('sass-loader'),
                                    options: {
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                    },
                                },
                            ].filter(Boolean),
                        },
                        {
                            test: lessRegex,
                            exclude: lessModuleRegex,
                            use: [
                                isEnvDevelopment && require.resolve('style-loader'),
                                isEnvProduction && {
                                    loader: MiniCssExtractPlugin.loader,
                                    options: {},
                                },
                                {
                                    loader: 'css-loader',
                                    options: {
                                        importLoaders: 3,
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                        modules: {
                                            mode: 'icss',
                                        },
                                    },
                                },
                                {
                                    loader: 'postcss-loader',
                                    options: {
                                        postcssOptions: {
                                            plugins: [
                                                'tailwindcss',
                                                'postcss-flexbugs-fixes',
                                                [
                                                    'postcss-preset-env',
                                                    {
                                                        autoprefixer: {
                                                            flexbox: 'no-2009',
                                                        },
                                                        stage: 3,
                                                    },
                                                ],
                                                'postcss-normalize',
                                            ],
                                        },
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                    },
                                },
                                {
                                    loader: require.resolve('less-loader'),
                                    options: {
                                        lessOptions: {
                                            strictMath: true,
                                            javascriptEnabled: true,
                                            modifyVars: {
                                                // colorPrimary: 'red',
                                            },
                                        },
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                    },
                                },
                            ].filter(Boolean),
                            sideEffects: true,
                        },
                        {
                            test: lessModuleRegex,
                            use: [
                                isEnvDevelopment && require.resolve('style-loader'),
                                isEnvProduction && {
                                    loader: MiniCssExtractPlugin.loader,
                                    options: {},
                                },
                                {
                                    loader: 'css-loader',
                                    options: {
                                        importLoaders: 3,
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                        modules: {
                                            mode: 'local',
                                            localIdentName: '[local]_[hash:base64:6]',
                                        },
                                    },
                                },
                                {
                                    loader: 'postcss-loader',
                                    options: {
                                        postcssOptions: {
                                            plugins: [
                                                'tailwindcss',
                                                'postcss-flexbugs-fixes',
                                                [
                                                    'postcss-preset-env',
                                                    {
                                                        autoprefixer: {
                                                            flexbox: 'no-2009',
                                                        },
                                                        stage: 3,
                                                    },
                                                ],
                                                'postcss-normalize',
                                            ],
                                        },
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                    },
                                },
                                {
                                    loader: 'less-loader',
                                    options: {
                                        lessOptions: {
                                            javascriptEnabled: true,
                                            modifyVars: {
                                                // colorPrimary: 'red',
                                            },
                                        },
                                        sourceMap: isEnvProduction ? false : isEnvDevelopment,
                                    },
                                },
                            ].filter(Boolean),
                        },
                        {
                            test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
                            loader: 'url-loader',
                            options: {
                                limit: 50 * 1024,
                                name: 'static/images/[name]-[hash:5].[ext]',
                                esModule: false,
                            },
                            type: 'javascript/auto',
                        },
                        {
                            test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
                            exclude: [path.resolve(__dirname, '../src/assets')],
                            use: [
                                {
                                    loader: 'url-loader',
                                    options: {
                                        name: '[name]-[hash].[ext]',
                                        outputPath: 'images/',
                                        limit: 204800,
                                    },
                                },
                            ],
                        },
                        {
                            test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
                            include: [path.resolve(__dirname, '../src/assets')],
                            use: [
                                {
                                    loader: 'babel-loader',
                                    options: {
                                        presets: ['@babel/preset-react', '@babel/preset-env'],
                                    },
                                },
                                {
                                    loader: '@svgr/webpack',
                                    options: {
                                        babel: false,
                                        icon: true,
                                    },
                                },
                            ],
                        },
                        {
                            exclude: [/^$/, /\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
                            type: 'asset/resource',
                        },
                    ],
                },
            ],
            parser: {
                javascript: {
                    exportsPresence: 'error',
                },
            },
        },
        plugins: [
            new webpack.ProgressPlugin(),
            new CleanWebpackPlugin({
                cleanOnceBeforeBuildPatterns: [path.resolve(__dirname, '../dist/*')],
            }),
            isEnvProduction &&
                new CopyWebpackPlugin({
                    patterns: [
                        path.resolve(__dirname, '../public/favicon.ico'),
                        path.resolve(__dirname, '../public/logo192.png'),
                        path.resolve(__dirname, '../public/logo512.png'),
                        path.resolve(__dirname, '../public/manifest.json'),
                    ],
                }),
            new HtmlWebpackPlugin(
                Object.assign(
                    {
                        inject: 'body' as 'body',
                        template: path.resolve(__dirname, '../public/index.html'),
                        // favicon: path.resolve(__dirname, '../public/favicon.ico'), // 这里添加的无type
                        title: '我的应用',
                        publicPath: publicPathOrUrl, //默认output.publicPath
                        publicPathOrUrl: publicUrl, //去掉末尾的/
                    },
                    isEnvProduction
                        ? {
                              minify: {
                                  removeComments: true,
                                  collapseWhitespace: true,
                                  removeRedundantAttributes: true,
                                  useShortDoctype: true,
                                  removeEmptyAttributes: true,
                                  removeStyleLinkTypeAttributes: true,
                                  keepClosingSlash: true,
                                  minifyJS: true,
                                  minifyCSS: true,
                                  minifyURLs: true,
                              },
                          }
                        : undefined,
                ),
            ),
            new webpack.DefinePlugin(stringified),
            isEnvProduction &&
                new MiniCssExtractPlugin({
                    filename: 'static/css/[name].[contenthash:8].css',
                    chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
                }),
            new WebpackManifestPlugin({
                fileName: 'asset-manifest.json',
                publicPath: publicPathOrUrl, //默认output.publicPath
                generate: (seed: any, files: any, entrypoints: any) => {
                    const manifestFiles = files.reduce((manifest: any, file: any) => {
                        manifest[file.name] = file.path;
                        return manifest;
                    }, seed);
                    const entrypointFiles = entrypoints.main.filter((fileName: string) => !fileName.endsWith('.map'));

                    return {
                        files: manifestFiles,
                        entrypoints: entrypointFiles,
                    };
                },
            }),
            // 开启webpack热更新功能
            isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
            isEnvProduction &&
                new BundleAnalyzerPlugin({
                    analyzerMode: 'static',
                    // analyzerMode: 'server',
                    // analyzerMode: 'disabled',
                    // analyzerHost: '127.0.0.1',
                    // analyzerPort: 8888,
                    reportFilename: 'report.html',
                    defaultSizes: 'gzip',
                    generateStatsFile: true, // 如果为true，则Webpack Stats JSON文件将在bundle输出目录中生成
                    openAnalyzer: false, // 默认在浏览器中自动打开报告
                    statsFilename: 'stats.json', // 如果generateStatsFile为true，将会生成Webpack Stats JSON文件的名字
                    statsOptions: { source: false },
                }),
        ].filter(Boolean),
        performance: false,
    };
}
export default configFactory;
